﻿/*********************************************************************
 * @file   FITKPlateCurvature.h
 * @brief  板件类型识别
 * @author zhangjingxuan (hiter25@outlook.com)
 * @date   2024-11-12
 *********************************************************************/
#ifndef __FITKPLATECURVATURE_H__
#define __FITKPLATECURVATURE_H__
#include "FITK2DMeshToolsAPI.h"
#include "FITKAbstractPlateCurvature.h"
#include "OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh"
#include <QList>
#include <QSet>

namespace Core
{
    class FITKNode;
    class FITKPoint;
}

namespace Interface
{
    class FITKElementTri3;
}

namespace Interface
{
    /**
     * @brief  板件识别，包括平板、单曲率板、双曲率板
     * @author zhangjingxuan (hiter25@outlook.com)
     * @date   2024-11-12
     */
    class FITK2DMeshToolsAPI FITKPlateCurvature : public FITKAbstractPlateCurvature
    {
    public:
        /**
         * @brief  OpenMesh网格精度设置double
         * @author zhangjingxuan (hiter25@outlook.com)
         * @date   2024-12-27
         */
        struct PolyTraits : public OpenMesh::DefaultTraits 
        {
            typedef OpenMesh::Vec3d Point;
            typedef OpenMesh::Vec3d Normal;
        };
        typedef OpenMesh::TriMesh_ArrayKernelT<PolyTraits>  FITKPlateMesh;
    public:
        FITKPlateCurvature();
        ~FITKPlateCurvature();
    public:
        /**
         * @brief    获取板的类型
         * @param[i] meshPoints 网格点
         * @param[i] meshFaces 网格单元
         * @return   int 0为平板，1为单曲率板，2为双曲率板
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-06
         */
        int getPlateType(const QList<Core::FITKNode*>& meshPoints, const QList<Interface::FITKElementTri3*>& meshFaces) override;
        /**
         * @brief    获取曲率半径
         * @param[i] plateType 板类型,0为平板，1为单曲率板，2为双曲率板
         * @return   QList<double> 返回曲率半径,平板0个,单曲率版1个,双曲率板2个
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-18
         */
        QList<double> getCurvatureRadius(const int& plateType) override;
    private:
        /**
         * @brief    初始化板网格数据
         * @param[i] meshPoints 网格点
         * @param[i] meshFaces 网格单元
         * @return   bool true初始化成功，false初始化失败
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-06
         */
        bool initPlateMesh(const QList<Core::FITKNode*>& meshPoints, const QList<Interface::FITKElementTri3*>& meshFaces);
        /**
         * @brief    获取板的边界点
         * @return   void
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-11
         */
        QSet<int> getBoundary();
        /**
         * @brief    获取局部点曲面特征
         * @param[i] vertex 网格点
         * @param[i] pArea 存储点邻域所有三角形面积
         * @return   int 返回局部点特征，0为平面，1为单曲率面，2为双曲率面
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-12
         */
        int pointFeature(const OpenMesh::TriMesh_ArrayKernelT<>::VertexHandle& vertex, double& pArea);
        /**
         * @brief    海伦公式计算三角形面积
         * @param[i] a 三角形边长a
         * @param[i] b 三角形边长b
         * @param[i] c 三角形边长c
         * @return   double 三角形面积
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-10
         */
        double calTriArea(const double& a, const double& b, const double& c);
        /**
         * @brief    计算Voronoi区域面积
         * @param[i] vertex 网格点
         * @param[i] costheta 存储点与相邻点之间夹角余弦值
         * @param[i] meancuroperator 存储平均曲率算子的一部分,1/2（|OQ|cot∠P + |OP|cot∠Q）
         * @param[i] pArea 存储点邻域所有三角形面积
         * @return   double 返回Voronoi区域面积
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-12
         */
        double calVoronoiArea(const OpenMesh::TriMesh_ArrayKernelT<>::VertexHandle& vertex, QList<double>& costheta, OpenMesh::Vec3d& meancuroperator, double& pArea);
        /**
         * @brief    计算点的高斯曲率 （2pi-∑theta）/ vArea
         * @param[i] vArea Voronoi区域面积
         * @param[i] costheta 中心点与两个相邻点之间加角
         * @return   double 返回网格点高斯曲率
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-11
         */
        double calGaussianCurvature(const double& vArea, const QList<double>& costheta);
        /**
         * @brief    计算点的平均曲率 meanCurOperator / vArea
         * @param[i] vArea vArea Voronoi区域面积
         * @param[i] meanCurOperator meanCurOperator 平均曲率算子的一部分,1/2（|OQ|cot∠P + |OP|cot∠Q）
         * @return   double 返回网格点平均曲率
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-11
         */
        double calMeanCurvature(const double& vArea, OpenMesh::Vec3d& meanCurOperator);
        /**
         * @brief    计算点的主曲率
         * @param[i] gaussianCurvature 高斯曲率
         * @param[i] meanCurvature 平均曲率
         * @return   QPair<double,double> 返回两个主曲率k1,k2
         * @author   zhangjingxuan (hiter25@outlook.com)
         * @date     2024-12-17
         */
        QPair<double, double> calPrincipalCurvature(const double& gaussianCurvature, const double& meanCurvature);
    private:
        /**
         * @brief  OpenMesh网格对象
         * @author zhangjingxuan (hiter25@outlook.com)
         * @date   2024-12-09
         */
        FITKPlateMesh* m_mesh{ nullptr };
        /**
         * @brief  主曲率k1,k2
         * @author zhangjingxuan (hiter25@outlook.com)
         * @date   2024-12-17
         */
        QList<QPair<double, double>> m_principalCurvature{};
    };
}
#endif // !__FITKPLATECURVATURE_H__